#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
更新Android客户端以支持基于权限的患者管理
"""

import os
import re
import shutil
from datetime import datetime

def backup_file(file_path):
    """备份文件"""
    if os.path.exists(file_path):
        backup_path = f"{file_path}.backup_{int(datetime.now().timestamp())}"
        shutil.copy2(file_path, backup_path)
        print(f"✅ 备份文件: {backup_path}")
        return backup_path
    return None

def update_websocket_manager():
    """更新WebSocketManager以支持权限"""
    file_path = "app/src/main/java/com/example/myapplication/realtime/WebSocketManager.kt"
    
    if not os.path.exists(file_path):
        print("❌ WebSocketManager.kt 文件不存在")
        return False
    
    backup_file(file_path)
    
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # 添加权限相关的消息类型
        permission_messages = '''
    // 权限相关消息类型
    fun sendAuthMessage(username: String, password: String) {
        if (isConnected.get()) {
            val authMessage = RealtimeMessage(
                type = MessageType.AUTH,
                data = AuthData(
                    username = username,
                    password = password,
                    timestamp = System.currentTimeMillis()
                )
            )
            sendMessage(authMessage)
            Log.d(TAG, "认证消息发送成功: $username")
        } else {
            Log.w(TAG, "WebSocket未连接，无法发送认证消息")
        }
    }
    
    fun sendAddPatientMessage(
        name: String,
        gender: String,
        age: Int?,
        phone: String?,
        idCard: String?,
        examinationDate: String,
        diagnosis: String?,
        notes: String?,
        examinationName: String?,
        admissionDate: String?
    ) {
        if (isConnected.get()) {
            val addPatientMessage = RealtimeMessage(
                type = MessageType.ADD_PATIENT,
                data = AddPatientData(
                    name = name,
                    gender = gender,
                    age = age,
                    phone = phone,
                    idCard = idCard,
                    examinationDate = examinationDate,
                    diagnosis = diagnosis,
                    notes = notes,
                    examinationName = examinationName,
                    admissionDate = admissionDate,
                    timestamp = System.currentTimeMillis()
                )
            )
            sendMessage(addPatientMessage)
            Log.d(TAG, "患者信息发送成功: $name")
        } else {
            Log.w(TAG, "WebSocket未连接，无法发送患者信息")
        }
    }
    
    fun sendGetPatientsMessage() {
        if (isConnected.get()) {
            val getPatientsMessage = RealtimeMessage(
                type = MessageType.GET_PATIENTS,
                data = EmptyData(timestamp = System.currentTimeMillis())
            )
            sendMessage(getPatientsMessage)
            Log.d(TAG, "获取患者列表消息发送成功")
        } else {
            Log.w(TAG, "WebSocket未连接，无法获取患者列表")
        }
    }
    
    fun sendGetMyPatientsMessage() {
        if (isConnected.get()) {
            val getMyPatientsMessage = RealtimeMessage(
                type = MessageType.GET_MY_PATIENTS,
                data = EmptyData(timestamp = System.currentTimeMillis())
            )
            sendMessage(getMyPatientsMessage)
            Log.d(TAG, "获取我的患者列表消息发送成功")
        } else {
            Log.w(TAG, "WebSocket未连接，无法获取患者列表")
        }
    }
'''
        
        # 在类的最后添加权限相关方法
        class_end_pattern = r'(\s+companion object\s*\{[^}]*\}\s*)?(\s*\})\s*$'
        content = re.sub(class_end_pattern, permission_messages + r'\2', content)
        
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(content)
        
        print("✅ WebSocketManager.kt 更新完成")
        return True
        
    except Exception as e:
        print(f"❌ WebSocketManager.kt 更新失败: {e}")
        return False

def update_message_types():
    """更新消息类型枚举"""
    file_path = "app/src/main/java/com/example/myapplication/realtime/WebSocketManager.kt"
    
    if not os.path.exists(file_path):
        return False
    
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # 查找MessageType枚举并更新
        message_type_pattern = r'enum class MessageType\s*\{[^}]*\}'
        new_message_types = '''enum class MessageType {
    AUTH,
    AUTH_SUCCESS,
    AUTH_FAILED,
    USER_REGISTER,
    NEW_USER_REGISTRATION,
    GET_PENDING_USERS,
    PENDING_USERS_LIST,
    APPROVE_USER,
    ADD_PATIENT,
    ADD_PATIENT_SUCCESS,
    ADD_PATIENT_ERROR,
    NEW_PATIENT_ADDED,
    GET_PATIENTS,
    PATIENTS_LIST,
    GET_MY_PATIENTS,
    MY_PATIENTS_LIST,
    UPDATE_PATIENT,
    PATIENT_UPDATE,
    HEARTBEAT,
    HEARTBEAT_ACK,
    CONNECTION_ACK,
    ERROR
}'''
        
        if 'enum class MessageType' in content:
            content = re.sub(message_type_pattern, new_message_types, content, flags=re.DOTALL)
        else:
            # 如果不存在，添加到文件开头
            content = new_message_types + '\n\n' + content
        
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(content)
        
        print("✅ MessageType 枚举更新完成")
        return True
        
    except Exception as e:
        print(f"❌ MessageType 更新失败: {e}")
        return False

def create_permission_data_classes():
    """创建权限相关的数据类"""
    file_path = "app/src/main/java/com/example/myapplication/realtime/PermissionData.kt"
    
    content = '''package com.example.myapplication.realtime

import com.google.gson.annotations.SerializedName

/**
 * 权限相关数据类
 */

data class AuthData(
    val username: String,
    val password: String,
    val timestamp: Long
)

data class AuthSuccessData(
    @SerializedName("user_id") val userId: Long,
    @SerializedName("user_info") val userInfo: UserInfo,
    val permissions: UserPermissions,
    val timestamp: String
)

data class UserInfo(
    val id: Long,
    val username: String,
    @SerializedName("real_name") val realName: String,
    val department: String,
    @SerializedName("user_type") val userType: String
)

data class UserPermissions(
    @SerializedName("can_add_patients") val canAddPatients: Boolean,
    @SerializedName("can_view_all_patients") val canViewAllPatients: Boolean,
    @SerializedName("can_view_department_patients") val canViewDepartmentPatients: Boolean,
    @SerializedName("can_approve_users") val canApproveUsers: Boolean
)

data class AddPatientData(
    val name: String,
    val gender: String,
    val age: Int?,
    val phone: String?,
    @SerializedName("idCard") val idCard: String?,
    @SerializedName("examinationDate") val examinationDate: String,
    val diagnosis: String?,
    val notes: String?,
    @SerializedName("examinationName") val examinationName: String?,
    @SerializedName("admissionDate") val admissionDate: String?,
    val timestamp: Long
)

data class PatientInfo(
    val id: Long,
    val name: String,
    val gender: String,
    val age: Int?,
    val phone: String?,
    @SerializedName("examination_date") val examinationDate: String,
    val diagnosis: String?,
    val notes: String?,
    val reporter: String,
    @SerializedName("examination_name") val examinationName: String?,
    val department: String,
    @SerializedName("reported_by") val reportedBy: Long,
    val status: String,
    @SerializedName("created_at") val createdAt: String
)

data class PatientsListData(
    val patients: List<PatientInfo>,
    val count: Int,
    @SerializedName("user_permissions") val userPermissions: UserPermissionsInfo?,
    val timestamp: String
)

data class UserPermissionsInfo(
    @SerializedName("user_type") val userType: String,
    val department: String,
    @SerializedName("can_view_all") val canViewAll: Boolean
)

data class NewPatientAddedData(
    val id: Long,
    val name: String,
    val gender: String,
    val age: Int?,
    val department: String,
    val reporter: String,
    @SerializedName("reported_by") val reportedBy: Long,
    @SerializedName("examination_date") val examinationDate: String,
    val diagnosis: String?,
    val status: String,
    val timestamp: String
)

data class EmptyData(
    val timestamp: Long
)
'''
    
    try:
        os.makedirs(os.path.dirname(file_path), exist_ok=True)
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(content)
        
        print("✅ 权限数据类创建完成: PermissionData.kt")
        return True
        
    except Exception as e:
        print(f"❌ 权限数据类创建失败: {e}")
        return False

def update_login_activity():
    """更新LoginActivity以支持权限认证"""
    file_path = "app/src/main/java/com/example/myapplication/LoginActivity.kt"
    
    if not os.path.exists(file_path):
        print("❌ LoginActivity.kt 文件不存在")
        return False
    
    backup_file(file_path)
    
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # 添加WebSocket认证逻辑
        auth_logic = '''
        // WebSocket认证
        private fun authenticateWithWebSocket(username: String, password: String) {
            try {
                val webSocketManager = com.example.myapplication.realtime.WebSocketManager.getInstance(this)
                webSocketManager.sendAuthMessage(username, password)
                Log.d("LoginActivity", "WebSocket认证消息发送成功")
            } catch (e: Exception) {
                Log.e("LoginActivity", "WebSocket认证失败", e)
            }
        }
        
        // 处理认证成功
        private fun onAuthenticationSuccess(userInfo: com.example.myapplication.realtime.UserInfo, permissions: com.example.myapplication.realtime.UserPermissions) {
            // 保存用户信息到UserSession
            UserSession.currentUser = User(
                id = userInfo.id,
                username = userInfo.username,
                realName = userInfo.realName,
                department = userInfo.department,
                userType = when(userInfo.userType) {
                    "SUPER_ADMIN" -> UserType.SUPER_ADMIN
                    "DEPARTMENT_ADMIN" -> UserType.DEPARTMENT_ADMIN
                    else -> UserType.USER
                },
                isActive = true,
                isApproved = true,
                phone = ""
            )
            
            // 保存权限信息
            UserSession.userPermissions = permissions
            
            // 跳转到主界面
            val intent = Intent(this, MainActivity::class.java)
            intent.putExtra("user_type", userInfo.userType)
            intent.putExtra("department", userInfo.department)
            intent.putExtra("real_name", userInfo.realName)
            startActivity(intent)
            finish()
        }
'''
        
        # 在类的最后添加认证方法
        class_end_pattern = r'(\s*\})\s*$'
        content = re.sub(class_end_pattern, auth_logic + r'\1', content)
        
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(content)
        
        print("✅ LoginActivity.kt 更新完成")
        return True
        
    except Exception as e:
        print(f"❌ LoginActivity.kt 更新失败: {e}")
        return False

def update_add_patient_activity():
    """更新AddPatientActivity以支持权限控制"""
    file_path = "app/src/main/java/com/example/myapplication/AddPatientActivity.kt"
    
    if not os.path.exists(file_path):
        print("❌ AddPatientActivity.kt 文件不存在")
        return False
    
    backup_file(file_path)
    
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # 添加WebSocket发送逻辑
        websocket_logic = '''
        // 通过WebSocket发送患者信息
        private fun sendPatientViaWebSocket() {
            try {
                val webSocketManager = com.example.myapplication.realtime.WebSocketManager.getInstance(this)
                webSocketManager.sendAddPatientMessage(
                    name = editName.text.toString(),
                    gender = spinnerGender.selectedItem.toString(),
                    age = editAge.text.toString().toIntOrNull(),
                    phone = editPhone.text.toString(),
                    idCard = editIdCard.text.toString(),
                    examinationDate = editExaminationDate.text.toString(),
                    diagnosis = editDiagnosis.text.toString(),
                    notes = editNotes.text.toString(),
                    examinationName = editExaminationName.text.toString(),
                    admissionDate = editAdmissionDate.text.toString()
                )
                Log.d("AddPatientActivity", "患者信息通过WebSocket发送成功")
            } catch (e: Exception) {
                Log.e("AddPatientActivity", "WebSocket发送患者信息失败", e)
            }
        }
'''
        
        # 在类的最后添加WebSocket方法
        class_end_pattern = r'(\s*\})\s*$'
        content = re.sub(class_end_pattern, websocket_logic + r'\1', content)
        
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(content)
        
        print("✅ AddPatientActivity.kt 更新完成")
        return True
        
    except Exception as e:
        print(f"❌ AddPatientActivity.kt 更新失败: {e}")
        return False

def create_user_session():
    """创建UserSession类来管理用户状态"""
    file_path = "app/src/main/java/com/example/myapplication/UserSession.kt"
    
    content = '''package com.example.myapplication

import com.example.myapplication.realtime.UserPermissions

/**
 * 用户会话管理
 */
object UserSession {
    var currentUser: User? = null
    var userPermissions: UserPermissions? = null
    
    fun isLoggedIn(): Boolean {
        return currentUser != null
    }
    
    fun canAddPatients(): Boolean {
        return userPermissions?.canAddPatients ?: false
    }
    
    fun canViewAllPatients(): Boolean {
        return userPermissions?.canViewAllPatients ?: false
    }
    
    fun canViewDepartmentPatients(): Boolean {
        return userPermissions?.canViewDepartmentPatients ?: false
    }
    
    fun canApproveUsers(): Boolean {
        return userPermissions?.canApproveUsers ?: false
    }
    
    fun getUserType(): UserType? {
        return currentUser?.userType
    }
    
    fun getDepartment(): String? {
        return currentUser?.department
    }
    
    fun getUserId(): Long? {
        return currentUser?.id
    }
    
    fun getRealName(): String? {
        return currentUser?.realName
    }
    
    fun logout() {
        currentUser = null
        userPermissions = null
    }
}
'''
    
    try:
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(content)
        
        print("✅ UserSession.kt 创建完成")
        return True
        
    except Exception as e:
        print(f"❌ UserSession.kt 创建失败: {e}")
        return False

def create_cross_network_guide():
    """创建跨网络配置指南"""
    content = '''# 基于权限的跨网络患者管理系统配置指南

## 🎯 系统特性

### 权限控制
- **普通用户 (USER)**: 只能看到自己上报的患者信息
- **科室管理员 (DEPARTMENT_ADMIN)**: 只能看到本科室人员上报的患者信息  
- **超级管理员 (SUPER_ADMIN)**: 可以看到所有科室的患者信息

### 实时传输
- 普通用户上报患者信息
- 科室管理员和管理员实时收到通知
- 支持跨网络环境

## 📋 快速配置步骤

### 1. 启动服务器
```bash
python permission_based_websocket_server.py
```

### 2. 配置跨网络访问

#### 方案A: 移动热点 (推荐)
1. 开启手机移动热点
2. 让所有设备连接到同一热点WiFi
3. 获取热点IP地址 (通常是 192.168.x.x)
4. 更新Android配置

#### 方案B: Cloudflare Tunnel
1. 下载 cloudflared.exe
2. 运行: `cloudflared tunnel --url localhost:8080`
3. 获取公网地址 (https://xxx.trycloudflare.com)
4. 更新Android配置

### 3. 更新Android配置
```bash
python update_android_config.py --server [服务器地址]
```

### 4. 重新编译APK
```bash
gradlew assembleRelease
```

### 5. 安装到设备
```bash
adb install -r app/build/outputs/apk/release/app-release.apk
```

## 👥 测试用户账号

### 超级管理员
- 用户名: `super_admin` / 密码: `super123`
- 用户名: `admin` / 密码: `admin123`

### 科室管理员
- 内科主任: `dept_admin_neike` / 密码: `dept123`
- 外科主任: `dept_admin_waike` / 密码: `dept123`

### 普通用户
- 内科医生: `user_neike1` / 密码: `user123`
- 外科医生: `user_waike1` / 密码: `user123`

## 🧪 测试流程

### 场景1: 普通用户上报患者
1. 用 `user_neike1` 登录 (内科医生)
2. 添加患者信息
3. 确认只能看到自己上报的患者

### 场景2: 科室管理员查看
1. 用 `dept_admin_neike` 登录 (内科主任)
2. 查看患者列表
3. 确认能看到内科所有医生上报的患者
4. 确认看不到外科的患者

### 场景3: 实时通知
1. 在不同网络的设备上登录不同角色
2. 普通用户添加患者
3. 科室管理员和超级管理员实时收到通知

### 场景4: 权限隔离
1. 外科医生登录，添加患者
2. 内科主任确认看不到外科患者
3. 超级管理员确认能看到所有患者

## 🔧 故障排除

### 连接问题
1. 检查服务器是否运行: `netstat -an | findstr :8080`
2. 检查网络连通性
3. 确认防火墙设置

### 权限问题
1. 确认用户账号和密码正确
2. 检查用户类型和科室设置
3. 查看服务器日志

### 实时通知问题
1. 确认WebSocket连接正常
2. 检查用户认证状态
3. 验证权限匹配

## 📊 系统架构

```
普通用户 (不同网络)
    ↓ WebSocket
跨网络传输 (热点/Tunnel)
    ↓
权限控制服务器
    ↓ 实时广播
科室管理员 + 超级管理员 (不同网络)
```

## 🌐 网络拓扑

```
真机A (普通用户) → 网络1
    ↓
WebSocket服务器 (权限控制)
    ↓
模拟器B (科室管理员) → 网络2
真机C (超级管理员) → 网络3
```

完成配置后，系统将支持基于权限的跨网络实时患者信息管理！
'''
    
    try:
        with open('跨网络权限管理配置指南.md', 'w', encoding='utf-8') as f:
            f.write(content)
        
        print("✅ 跨网络权限管理配置指南.md 创建完成")
        return True
        
    except Exception as e:
        print(f"❌ 配置指南创建失败: {e}")
        return False

def main():
    """主函数"""
    print("🔄 更新Android客户端以支持基于权限的患者管理...")
    print("=" * 60)
    
    tasks = [
        ("创建权限数据类", create_permission_data_classes),
        ("更新消息类型", update_message_types),
        ("更新WebSocketManager", update_websocket_manager),
        ("更新LoginActivity", update_login_activity),
        ("更新AddPatientActivity", update_add_patient_activity),
        ("创建UserSession", create_user_session),
        ("创建配置指南", create_cross_network_guide)
    ]
    
    success_count = 0
    
    for task_name, task_func in tasks:
        print(f"\n📝 {task_name}...")
        if task_func():
            success_count += 1
        else:
            print(f"⚠️ {task_name} 失败")
    
    print("\n" + "=" * 60)
    print(f"📊 更新结果: {success_count}/{len(tasks)} 任务完成")
    
    if success_count == len(tasks):
        print("✅ 所有更新完成！")
        print("\n📝 下一步:")
        print("1. 重新编译APK: gradlew assembleRelease")
        print("2. 安装到设备: adb install -r app/build/outputs/apk/release/app-release.apk")
        print("3. 配置跨网络访问")
        print("4. 使用测试账号进行权限测试")
        print("\n📖 详细指南: 跨网络权限管理配置指南.md")
    else:
        print("⚠️ 部分更新失败，请检查错误信息")

if __name__ == "__main__":
    main() 